package com.jy.api.controller.MarsCall;

import com.baidu.aip.speech.AipSpeech;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.jy.api.config.WebSocketUrlUtils;
import com.jy.api.controller.admin.params.RegionEditParams;
import com.jy.api.dao.*;
import com.jy.api.domain.*;
import com.jy.api.enums.OrderPayChannel;
import com.jy.api.enums.PayTypeEnum;
import com.jy.api.exception.CallServiceException;
import com.jy.api.payReq.ALLPayQrCodeResult;
import com.jy.api.service.CallService;
import com.jy.api.service.*;
import com.jy.api.service.impl.*;
import com.jy.api.signUpReq.*;
import com.jy.api.signUpReq.MarsCallReq.*;
import com.jy.api.util.Result;
import com.jy.api.util.*;
import com.jy.api.vo.admin.product.ProductTypeVo;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by xiaohua on 2018/11/9.
 */
@RestController
@Slf4j
@RequestMapping(value = "/v1/call", produces = "application/json;charset=utf-8")
public class MarsCallController {


    @Autowired
    protected WxPayService wxPayService;
    @Autowired
    protected MemberDao memberDao;
    @Autowired
    private CallConfigDao callConfigDao;
    @Autowired
    ProductDao productDao;
    @Autowired
    private StoreService storeService;
    @Autowired
    private AppraiseNetService netService;
    @Autowired
    private ProductService productService;
    @Autowired
    private AppraiseService appraiseService;
    @Autowired
    private CallService callService;
    @Autowired
    private RewardService rewardService;
    @Autowired
    private EmployeeService employeeService;
    @Autowired
    private PaymentService paymentService;
    @Autowired
    private WechatService wechatService;
    @Autowired
    private RewardDao rewardDao;
    @Autowired
    private StoreDao storeDao;
    @Autowired
    private WithdrawService withdrawService;
    @Autowired
    private StoreOrderService storeOrderService;
    @Autowired
    private CallTranService callTranService;
    @Autowired
    private WebSocketUrlUtils urlUtils;
    @Autowired
    private CallTranDao callTranDao;
    @Autowired
    private OrderService orderService;
    @Autowired
    private StorePayDao storePayDao;
    @Autowired
    private HSServiceImpl hsService;
    @Autowired
    private JLServiceImpl jlService;
    @Autowired
    private SaoBeiServiceImpl saoBeiService;
    @Autowired
    private JdbcTemplate jdbc;
    @Autowired
    private ProductTypeService productTypeService;
    @Autowired
    private ProductTypeDao productTypeDao;
    @Autowired
    private HuiFuServiceImpl huiFuService;
    @Autowired
    private SuiXinFuServiceImpl suiXinFuService;
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private AliyunMNSSend aliyunMNSSend;
    @Autowired
    private PaymentServiceImpl service;
    @Resource
    private RedisSyncLocker redisSyncLocker;
    @Autowired
    private AccountBalanceDao accountBalanceDao;
    @Autowired
    private EmployeeDao employeeDao;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Resource
    private RedisService redisService;
    @Resource
    private OrderItemDao orderItemDao;
    @Resource
    private StockTransactionDao stockTransactionDao;
    @Autowired
    private RegionDao regionDao;

    @Resource
    private Environment environment;
    public static PropertiesLoader getApplicationProperties() {
        return new PropertiesLoader("application.properties", String.format("application%s.properties", ""));
    }

    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("X-real-ip");//先从nginx自定义配置获取
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("x-forwarded-for");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    @PostMapping("/lease/enabled")
    public ResponseEntity leaseEnabled(@RequestBody StoreMessageReq req) {
        Store store = storeDao.findOne(req.getStoreId());
        store.setLeaseProductEnabled(req.isLeaseProductEnabled());
        if (StringUtils.isNotBlank(req.getLeaseBeginDate())){
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
            try {
                store.setLeaseBeginDate(sdf.parse(req.getLeaseBeginDate()));
                store.setLeaseEndDate(sdf.parse(req.getLeaseEndDate()));
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        storeDao.save(store);
        return ResponseEntity.ok().body("开启/关闭成功");
    }
    @PostMapping("/return/enabled")
    public ResponseEntity returnEnabled(@RequestBody StoreMessageReq req) {
        Store store = storeDao.findOne(req.getStoreId());
        store.setReturnCallEnabled(req.isReturnCallEnabled());
        storeDao.save(store);
        return ResponseEntity.ok().body("开启/关闭成功");
    }


    @PostMapping("/region/list")
    public ResponseEntity list(@RequestBody RegionEditParams params) {
        List<Region> region = regionDao.findByStoreIdOrderByQueueDesc(params.getStoreId());
        return ResponseEntity.ok(region);
    }
    @GetMapping("get-marsIndex")
    public ResponseEntity getMarsCallList(@RequestParam("storeId") String storeId) {
        try {
            return ResponseEntity.ok(storeService.findMarsCallIndex(storeId));
        } catch (Exception e) {
            log.info("获取呼叫打赏首页异常{}",e);
            return new ResponseEntity("系统运行错误", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @ApiOperation(value = "批量导入商品")
    @PostMapping("/batch/upload")
    public ResponseEntity itemLibDetail(@RequestBody RegionEditParams params) throws Exception {
        List<LinkedHashMap<String, String>> linkedHashMaps =DealWxTxtUtils. alibabaEasyExcel(params.getUrl());
       //{0=龙烟呈祥, 1=香烟, 2=15.0, 3=6, 4=10, 5=16}
        //吧台   仓库  平台可销
        List<ProductType> productTypes = productTypeDao.findListByStoreIdAndEnabledOrderBySequenceAsc(params.getStoreId(),true);
        HashMap map = new HashMap();
        for (ProductType productType : productTypes) {
            map.put(productType.getName(),productType);
        }
        for (LinkedHashMap<String, String> hashMap : linkedHashMaps) {
            Product product = new Product();
            product.setId(UuidUtil.getUuid());
            product.setStoreId(params.getStoreId());
            product.setProductType((ProductType) map.get(hashMap.get(1)));
            product.setName(hashMap.get(0));
            product.setPinyin(PinYinUtil.getFirstSpell(product.getName()));
            product.setSalesPrice(Double.parseDouble(hashMap.get(2)));
            product.setQuantity(Integer.parseInt(hashMap.get(3)));
            product.setStockEnabled(true);
            product.setPurchaseEnabled(true);
            product.setShowEnabled(true);
            productDao.save(product);
        }
        return ResponseEntity.ok().build();
    }
    @GetMapping("/update/product")
    public ResponseEntity updateProductId(@RequestParam("productTypeId") String productTypeId) {
        orderItemDao.updateByProductTypeId(productTypeId);
        return ResponseEntity.ok().build();
    }
  /*  @GetMapping("/refund/test")
    public ResponseEntity refundTest(@RequestParam("productTypeId") String id) {
            Order order = orderDao.findOne(id);
            if (order!=null){
                StorePay storePay = storePayDao.findByStoreIdAndStartEnabled(order.getStoreId(), true);
                try {
                    suiXinFuService.suixinfuRefundTest(order.getId(),order,storePay,(order.getAmount()-2)+"");
                    suiXinFuService.suixinfuOrderQRCodeTest(storePay,order);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return ResponseEntity.ok().build();
    }

    @GetMapping("/ledger/test")
    public ResponseEntity ledgerAccountFlag(@RequestParam("id") String id) {
        Order order = orderDao.findOne(id);
        if (order!=null){
            StorePay storePay = storePayDao.findByStoreIdAndStartEnabled(order.getStoreId(), true);
            try {
                suiXinFuService.suixinfuOrderQRCodeTest(storePay,order);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return ResponseEntity.ok().build();
    }
*/
    @GetMapping("/batch/service")
    public ResponseEntity updateMarsCallService(@RequestParam(value = "storeId", required = false) String storeId) throws Exception {
        if (StringUtils.isNotBlank(storeId)) {
            ImageFileOssUtil.downloadCallAndServiceUpload(storeId);
        } else {
            List<Store> store = storeDao.findByCallIsTrueAndCallEndTimeGreaterThanEqual(new Date());
            for (Store store1 : store) {
                ImageFileOssUtil.downloadCallAndServiceUpload(store1.getId());
            }
        }
        return ResponseEntity.ok().body("操作成功");
    }

    @GetMapping("update/image")
    public ResponseEntity updateImage() {
        try {
            List<Product> products = productDao.findAllByEnabledIsTrue();
            for (Product product : products) {
                if (StringUtils.isNotBlank(product.getImageURL())) {
                    if (product.getImageURL().contains("hxypic.oss-cn-hangzhou.aliyuncs.com")) {
                        product.setImageURL(product.getImageURL().replace("hxypic.oss-cn-hangzhou.aliyuncs.com", "images.huoxingy.com"));
                    }
                }
            }
            productDao.save(products);
            List<Employee> employees = employeeDao.findAllByEnabledIsTrue();
            for (Employee employee : employees) {
                if (StringUtils.isNotBlank(employee.getPhoto())) {
                    if (employee.getPhoto().contains("hxypic.oss-cn-hangzhou.aliyuncs.com")) {
                        employee.setPhoto(employee.getPhoto().replace("hxypic.oss-cn-hangzhou.aliyuncs.com", "images.huoxingy.com"));
                    }
                }

            }
            employeeDao.save(employees);
            return ResponseEntity.ok("操作成功");
        } catch (Exception e) {
            System.out.println(e);
            return new ResponseEntity("系统运行错误", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @GetMapping("/deal/type")
    public ResponseEntity giftRefund() {
        List<Product> saveProducts = new ArrayList<>();
        List<ProductType> productTypes = productTypeDao.findByEnabled(true);
        for (ProductType productType : productTypes) {
            //2级分类 有商品
            List<Product> list = productDao.findByStoreIdAndEnabledAndProductType(productType.getStoreId(), true, productType);
            for (Product product : list) {
                product.setParentTypeName(null == productType.getParent() ? productType.getName() : productType.getParent().getName());
                product.setTypeName(productType.getName());
                saveProducts.add(product);
            }
        }
        productDao.save(saveProducts);
        return new ResponseEntity(HttpStatus.OK);
    }

    @GetMapping("deal-address")
    public ResponseEntity dealAddress() {
        List<Store> list = storeDao.findListByEnabled(true);
        for (Store store : list) {
            List<StorePay> storePays = storePayDao.findByStoreId(store.getId());
            for (StorePay storePay : storePays) {
                if (null != store.getAddr()) {
                    storePay.setAddress(store.getAddr());
                    storePayDao.save(storePay);
                }
            }
        }
        return ResponseEntity.ok("操作完成");
    }

    @GetMapping("deal-mq")
    public ResponseEntity dealMq(@RequestParam("begin") String begin, @RequestParam("end") String end) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        df.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        try {
            Date beginTime = df.parse(begin);
            Date endTime = df.parse(end);
            List<Order> orders = orderDao.findAllByAddTimeBetweenAndStatus(beginTime, endTime, OrderStatus.NOTSURE);
            for (Order order : orders) {
                aliyunMNSSend.sendClint(order.getId());
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return ResponseEntity.ok("操作完成");

    }

    @PostMapping("appraise")
    public ResponseEntity appraiseStore(@RequestBody AppraiseNetRes netRes) {
        try {
            netService.appraiseStore(netRes);
            return ResponseEntity.ok("评价成功");
        } catch (Exception e) {
            log.info("get-netApp is error==>  storeId{}", netRes.getStoreId());
            return new ResponseEntity("系统运行错误", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @GetMapping("deal-data")
    public ResponseEntity dealData() {
        List<Store> stores = storeDao.findAllByEnabledAndExpireTimeGreaterThan(true, new Date());
        for (Store store : stores) {
            StorePay storePay = storePayDao.findByStoreIdAndStartEnabled(store.getId(), true);
            if (storePay == null) {
                StorePay pay = new StorePay();
                pay.setStoreName(store.getName());
                pay.setStoreId(store.getId());
                pay.setMchKey(store.getKey());
                pay.setChannel(OrderPayChannel.HUI_SHANG);
                pay.setMchId(store.getMchId());
                storePayDao.save(pay);
            }
        }
        return ResponseEntity.ok("店铺处理成功");
    }

    @PostMapping("store-pay-merge")
    public ResponseEntity storePayMerge(@RequestBody StorePayMergeReq req) {
        StorePay storeBillPay = storePayDao.findAllByChannelAndStoreId(req.getChannel(), req.getStoreId());
        Store store = storeDao.findOne(req.getStoreId());
        boolean status = false;
        if (storeBillPay == null) {
            status = true;
        }

        if (!status) {
            StorePay storePay = storePayDao.findOne(req.getId());
            if (storePay.isStartEnabled() && !req.isStartEnabled()) {
                return new ResponseEntity("商户必须默认一个支付渠道", HttpStatus.BAD_REQUEST);
            } else if (!storePay.isStartEnabled() && req.isStartEnabled()) {
                StorePay judge = storePayDao.findByStoreIdAndStartEnabled(req.getStoreId(), true);
                judge.setStartEnabled(false);
                storePayDao.save(judge);
                storePay.setStartEnabled(req.isStartEnabled());
                storePayDao.save(storePay);
            }
        }
        if (storeBillPay == null) {
            storeBillPay = new StorePay(req);
        } else {
            storeBillPay.setMchId(req.getMchId());
            if (req.getChannel().equals(OrderPayChannel.HUI_SHANG) || req.getChannel().equals(OrderPayChannel.JL)) {
                storeBillPay.setMchKey(req.getMchKey());
            } else if (req.getChannel().equals(OrderPayChannel.SAO_BEI)) {
                storeBillPay.setTerminalId(req.getTerminalId());
                storeBillPay.setAccessToken(req.getAccessToken());
            }
        }
        if (req.isStartEnabled() && status) {
            StorePay storePay = storePayDao.findByStoreIdAndStartEnabled(req.getStoreId(), true);
            storePay.setStartEnabled(false);
            storePayDao.save(storePay);
        }
        if (null != store.getAddr()) {
            storeBillPay.setAddress(store.getAddr());
        } else {
            storeBillPay.setAddress("");
        }
        storeBillPay.setStoreName(store.getName());
        storePayDao.save(storeBillPay);
        return ResponseEntity.ok("修改成功");
    }

    @PostMapping("get-month-sales")
    public ResponseEntity getMonthSales(@RequestBody MonthSalesReq req) {
        String sql = "SELECT  count(*) FROM information_schema.TABLES WHERE table_name = '" + "order_item_" + req.getMonth() + "' and TABLE_SCHEMA = 'hxbs-prod' ;";
        int count = jdbcTemplate.queryForObject(sql, Integer.class);
        if (count <= 0) {
            return ResponseEntity.badRequest().body("该月" + req.getMonth() + "数据不存在");
        }
        BeanPropertyRowMapper item = new BeanPropertyRowMapper<>(MonthSalesRes.class);
        item.setPrimitivesDefaultedForNullValue(true);
        System.out.println(req);
        String s = "";
        for (int i = 0; i < req.getTypeName().size(); i++) {
            if (i == req.getTypeName().size() - 1) {
                s += "'" + req.getTypeName().get(i) + "'";
            } else {
                s += "'" + req.getTypeName().get(i) + "',";
            }
        }
        String firstOrderSQL;
        if (s.equals("")) {
            firstOrderSQL = String.format("SELECT product.`parent_type_name` AS typeName,product.`name` AS name,product.`sales_price` AS salesPrice, ifnull(SUM(sales.amount), 0) as amount, ifnull(sum(sales.qty),0) AS qty, product.`type_name` AS parentTypeName FROM(SELECT * FROM `product` WHERE `store_id`= ?) as product  LEFT JOIN(SELECT sum(`quantity`) as qty, SUM(`deal_price`) as amount, `product_id` FROM `%s` oi WHERE `order_id` IN(SELECT id  FROM `%s`  WHERE `store_id`= ?  and `status`  in('FINISHED','UNFINISHED') AND `payment_time`>= ? AND `payment_time`<= ? AND `enabled`= 1) GROUP BY `product_id`) sales on product.id= sales.product_id  WHERE    qty>0 GROUP BY product.`name` order BY qty DESC ", "order_item_" + req.getMonth(), "order_" + req.getMonth());
        } else {
            firstOrderSQL = String.format("SELECT product.`parent_type_name` AS typeName,product.`name` AS name,product.`sales_price` AS salesPrice, ifnull(SUM(sales.amount), 0) as amount, ifnull(sum(sales.qty),0) AS qty, product.`type_name` AS parentTypeName FROM(SELECT * FROM `product` WHERE `store_id`= ?) as product  LEFT JOIN(SELECT sum(`quantity`) as qty, SUM(`deal_price`) as amount, `product_id` FROM `%s` oi WHERE `order_id` IN(SELECT id  FROM `%s`  WHERE `store_id`= ?  and `status`  in('FINISHED','UNFINISHED') AND `payment_time`>= ? AND `payment_time`<= ? AND `enabled`= 1) GROUP BY `product_id`) sales on product.id= sales.product_id  WHERE   product.`parent_type_name` IN (" + s + ") and  qty>0 GROUP BY product.`name` order BY qty DESC ", "order_item_" + req.getMonth(), "order_" + req.getMonth());
        }
        List<MonthSalesRes> SalesItemDetails = jdbc.query(firstOrderSQL, item, req.getStoreId(), req.getStoreId(), req.getBegin(), req.getEnd());
        return ResponseEntity.ok(SalesItemDetails);
    }

    @GetMapping("get-type")
    public ResponseEntity getType(@RequestParam("storeId") String storeId) {
        try {
            Store store = storeDao.findOne(storeId);
            if (store == null) {
                return new ResponseEntity("查询失败！店铺信息有误！", HttpStatus.BAD_REQUEST);
            }
            List<ProductTypeVo> productTypeList = new LinkedList<>();
            ProductType productType = productTypeDao.findOne("1");
            ProductTypeVo productTypeVo = new ProductTypeVo();
            BeanUtils.copyProperties(productType, productTypeVo);
            productTypeList.add(productTypeVo);

            List<ProductTypeVo> typeVos = productTypeService.getStoreTypes(storeId);
            productTypeList.addAll(typeVos);
            return new ResponseEntity(productTypeList, HttpStatus.OK);
        } catch (Exception ex) {
            log.error("getProductTypes is error=>storeId:{}", storeId, ex);
            return new ResponseEntity("系统运行错误", HttpStatus.INTERNAL_SERVER_ERROR);
        }


    }

    @GetMapping("get-gift")
    public ResponseEntity findGift() {
        try {
            return ResponseEntity.ok(productService.findGift());
        } catch (Exception e) {
            log.info("get-gift is error", e);
            return new ResponseEntity("系统运行错误", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @PostMapping("appraise-emp")
    public ResponseEntity appraiseEmp(@RequestBody AppraiseEmpReq req) {
        try {
            appraiseService.appraiseEmp(req);
            return ResponseEntity.ok("评价成功");
        } catch (Exception e) {
            log.info("appraise-emp is error ==> storeId{}", req.getStoreId());
            return new ResponseEntity("系统运行错误", HttpStatus.INTERNAL_SERVER_ERROR);
        }


    }

    @GetMapping("judge-call")
    public ResponseEntity judgeCallService(@RequestParam("empId") String empId, @RequestParam("storeId") String storeId, @RequestParam("tableNo") String tableNo) {
        try {
            return ResponseEntity.ok(callService.judgeCallService(empId, storeId, tableNo));
        } catch (Exception e) {
            log.info("call-service is error ==> storeId{},e", storeId, e);
            return new ResponseEntity("系统运行错误", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @PostMapping("call-service")
    public ResponseEntity callService(@RequestBody CallReq req) {
        try {
            return ResponseEntity.ok(callService.callService(req));
        } catch (Exception e) {
            log.info("call-service is error ==> storeId{},e", req.getStoreId(), e);
            return new ResponseEntity("系统运行错误", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @GetMapping("call-finish")
    public ResponseEntity callFinish(@RequestParam("id") int id) {
        try {
            return ResponseEntity.ok(callService.callFinish(id));
        } catch (CallServiceException e) {
            log.info("call-finish is error==> id{}", id);
            return new ResponseEntity(e.getMessage(), HttpStatus.BAD_REQUEST);
        } catch (Exception e) {
            log.info("call-finish is error ==> id{}", id);
            return new ResponseEntity("系统运行错误", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @PostMapping("reward-order")
    public ResponseEntity rewardOrder(@RequestBody RewardOrderReq req) {
        try {
            return ResponseEntity.ok(rewardService.createRewardOrder(req));
        } catch (Exception e) {
            log.info("reward-order is error ==> id{}", req.getStoreId());
            return new ResponseEntity("系统运行错误", HttpStatus.INTERNAL_SERVER_ERROR);
        }

    }

    @GetMapping("get-empCall")
    public ResponseEntity getEmpCall(@RequestParam("storeId") String storeId, Pageable pageable) {
        try {
            Store store = storeDao.findOne(storeId);
            if (store.isCall() && (new Date().getTime() - store.getCallEndTime().getTime()) > 0) {
                return new ResponseEntity("店铺语音呼叫已过期,请及时续费！", HttpStatus.BAD_REQUEST);
            }
            return ResponseEntity.ok(callService.findByStoreCallService(storeId, pageable));

        } catch (Exception e) {
            log.info("get-empCall is error ==> storeId{}", storeId);
            return new ResponseEntity("系统运行错误", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @PostMapping("update-work")
    public ResponseEntity updateEmpWork(@RequestBody EmpReq empReq) {
        return ResponseEntity.ok(employeeService.updateEmpWorkStatus(empReq));
    }

    @GetMapping("get-emp")
    public ResponseEntity getEmp(@RequestParam("storeId") String storeId) {
        return ResponseEntity.ok(employeeService.getEmpList(storeId));
    }

    @PostMapping("/scan-code")
    public ResponseEntity rewardPay(@RequestBody CallEmpRes res) {
        PayTypeEnum payType = res.isType() ? PayTypeEnum.PAY_ALIPAY_NATIVE : PayTypeEnum.PAY_WX_NATIVE;
        Reward reward = rewardDao.findOne(String.valueOf(res.getRewardId()));
        StorePay storePay = storePayDao.findByStoreIdAndStartEnabled("574b59ef-b19c-11e7-9233-37891743d141", true);
        ALLPayQrCodeResult result = new ALLPayQrCodeResult();
        Map<String, String> map = new HashMap();
        try {
            switch (storePay.getChannel()) {
                case JL:
                    result = jlService.JLRewardQRCode(reward);
                    break;
                case HUI_SHANG:
                    result = hsService.qrRewardCodePay(String.valueOf(res.getRewardId()), payType);
                    map.put("channel", "HUI_SHANG");
                    break;
                case SAO_BEI:
                    result = saoBeiService.saobeiRewardQrCode(storePay, reward);
                    map.put("channel", "SAO_BEI");
                    break;
                case HUI_FU:
                    result = huiFuService.huifuRewardQrCode(storePay, reward, payType);
                case SUI_XIN_FU:
                    result = suiXinFuService.suixinfuRewardQRCode(storePay, reward, payType);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("订单号{},扫呗打赏支付失败,e{}", reward.getId(), e);
        }
        map.put("payMode", "THIRD_PARTY");
        map.put("url", result.getCodeImgURL());
        if (result.isSuccess()) {
            return ResponseEntity.ok(map);
        } else {
            return ResponseEntity.badRequest().body(result.getErrMsg());
        }
    }

    @ApiOperation("商品支付")
    @PostMapping("/pay")
    public ResponseEntity pay(@RequestBody CallEmpRes res, HttpServletRequest request) throws Exception {
        Reward reward = rewardDao.findOne(String.valueOf(res.getRewardId()));
        if (reward == null) {
            return new ResponseEntity("订单暂时不存在，请重新下单", HttpStatus.INTERNAL_SERVER_ERROR);
        }
        Map map = new HashMap();
        final String wxNotifyUrl =String.format("https://%s/v1/call/wxCallBack",environment.getProperty("app.base.domain"));
        final WxPayNativeOrderResult wxPayNativeOrderResult = wxNativePay(service.getRewardBody(reward), reward.getId(), (long) Math.rint(reward.getTotal() * 100), reward.getId(), wxNotifyUrl, request);
        map.put("channel", "WEIXIN");
        map.put("payMode", "THIRD_PARTY");
        map.put("url", wxPayNativeOrderResult.getCodeUrl());
        return ResponseEntity.ok(map);
    }

    protected WxPayNativeOrderResult wxNativePay(String body, String orderNumber, long money, String productId, String notifyUrl, HttpServletRequest request) throws WxPayException {
        final WxPayUnifiedOrderRequest unifiedOrderRequest = WxPayUnifiedOrderRequest.newBuilder()
                .body(body)
                .productId(productId)
                .outTradeNo(orderNumber)
                .totalFee(Math.toIntExact(money))
                .spbillCreateIp(getIpAddress(request))
                .notifyUrl(notifyUrl)
                .tradeType(WxPayConstants.TradeType.NATIVE)
                .build();

        return wxPayService.createOrder(unifiedOrderRequest);
    }

    @ApiOperation("微信订单回调")
    @PostMapping("/wxCallBack")
    public String orderWxCallback(final HttpServletRequest request, HttpServletResponse response) throws Exception {
        try {
            String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
            WxPayOrderNotifyResult result = wxPayService.parseOrderNotifyResult(xmlResult);
            log.info("微信回调结果: {}", result);
            // 结果正确
            String orderId = result.getOutTradeNo();
            String tradeNo = result.getTransactionId();
            final Integer totalFee = result.getTotalFee();
            final String openid = result.getOpenid();
            if ("SUCCESS".equals(result.getReturnCode()) && "SUCCESS".equals(result.getResultCode())) {
                //自己处理订单的业务逻辑，需要判断订单是否已经支付过，否则可能会重复调用
                redisSyncLocker.StringKeyLock(orderId, o -> {
                    Reward reward = rewardDao.findOne(orderId);
                    if (reward.getStatus().equals(OrderStatus.INIT)) {
                        reward.setChannel("pay.wechat.native");
                        reward.setPaymentTime(new Date());
                        reward.setStatus(OrderStatus.FINISHED);
                        reward.setCommission(totalFee / 100.0);
                        reward.setCompanyAmount(totalFee / 1000.0);
                        AccountBalance accountBalance = accountBalanceDao.findByStoreId(reward.getStoreId());
                        log.info("accountBalance" + accountBalance);
                        if (accountBalance == null) {
                            accountBalance = new AccountBalance(totalFee / 100.0, reward.getStoreId());
                        } else {
                            accountBalance.setAmount(accountBalance.getAmount() + totalFee / 100.0);
                        }
                        rewardDao.save(reward);
                        accountBalanceDao.save(accountBalance);
                        notifyRewardNewCallService(reward, "wxCallBack:" + orderId);
                    }
                    return null;
                });
            }
            return WxPayNotifyResponse.success("处理成功!");
        } catch (Exception e) {
            log.error("微信回调结果异常,异常原因{}", e);
            return WxPayNotifyResponse.fail(e.getMessage());
        }
    }

    public void notifyRewardNewCallService(Reward reward, String mark) {
        if (redisService.canProceedCustom("notify" + reward.getId(), 24 * 60 * 60)) {
            Employee employee = employeeDao.findOne(reward.getEmpId());
            try {
                Map<String, String> map = new HashMap<>();
                map.put("tableNum", reward.getTableNo());
                map.put("empCode", employee.getCode());
                map.put("productName", reward.getProductName());
                map.put("qty", String.valueOf(reward.getCount()));
                map.put("empName", reward.getEmpName());
                map.put("storeId", reward.getStoreId());
                map.put("type", "REWARD");
                map.put("mark", mark);
                putWs(map);
            } catch (Exception e) {
                log.warn("Fail to send websocket notify to store:{}", reward.getStoreId());
            }
        }
    }

    private void putWs(Map<String, String> map) {
        try {
            //发送ws
            String url = urlUtils.getWs();
            OkHttpUtils.post(url, com.alibaba.fastjson.JSONObject.toJSONString(map));
        } catch (Exception ex) {
            log.error(" Invitation code initialization failed msg:{}", ex);
        }

    }

    @GetMapping("get-rewardItem")
    public ResponseEntity getRewardItem(@RequestParam("storeId") String storeId, Pageable pageable) {

        try {
            return ResponseEntity.ok(rewardService.getRewardItem(storeId, pageable));
        } catch (Exception e) {
            log.info("get-rewardItem is error ==> storeId{}", storeId);
            return new ResponseEntity("系统运行错误", HttpStatus.INTERNAL_SERVER_ERROR);
        }

    }


    @GetMapping("get-ranking")
    public ResponseEntity getRewardRanking(@RequestParam("storeId") String storeId, @RequestParam("empId") String empId) {
        try {
            return ResponseEntity.ok(rewardService.getRewardRanking(storeId, empId));
        } catch (Exception e) {
            log.info("get-ranking is error ==> storeId{}", e);
            return new ResponseEntity("系统运行错误", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @RequestMapping(method = RequestMethod.GET, value = "/wechat-binding")
    public ResponseEntity orderBinding(@RequestParam("storeId") String storeId, @RequestParam("orderId") String orderId) {
        try {
            String url = wechatService.getLogUrl(storeId, orderId);
            return new ResponseEntity(url, HttpStatus.OK);
        } catch (Exception ex) {
            log.error("login1 is error==> storeId:{},orderId:{}", storeId, ex);
            return new ResponseEntity("系统运行错误", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @GetMapping("rotation-reward")
    public ResponseEntity rotationReward(@RequestParam("id") String id) {

        try {
            Reward reward = rewardDao.findOne(id);
            Result result = null;
            if (reward.getStatus().equals(OrderStatus.FINISHED)) {
                paymentService.notifyRewardNewCallService(reward, "rotation-reward:" + id);
                result = new Result(200, "感谢您的打赏，我们会努力做得更好！");
            } else {
                result = new Result(201, "支付中，请等待");
            }
            return ResponseEntity.ok(result);
        } catch (Exception ex) {
            log.error("rotation-reward is error==> orderId:{}", id, ex);
            return new ResponseEntity("系统运行错误", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @GetMapping("get-sales-product")
    public ResponseEntity getSalesProduct(@RequestParam("storeId") String storeId, Pageable pageable) {
        return ResponseEntity.ok(productService.getSalesProduct(storeId, pageable));
    }


    @GetMapping("get-memberInfo")
    public ResponseEntity getMemberInfo(@RequestParam("id") String id) {

        try {
            return ResponseEntity.ok(rewardService.getMemberInfo(id));
        } catch (Exception ex) {
            log.error("get-memberInfo is error==> id:{}", id, ex);
            return new ResponseEntity("系统运行错误", HttpStatus.INTERNAL_SERVER_ERROR);
        }

    }

    @PostMapping("update-reward")
    public ResponseEntity updateReward(@RequestBody RewardUpdateReq req) {
        try {
            return ResponseEntity.ok(rewardService.updateReward(req));
        } catch (Exception e) {
            log.info("update-reward is error ==> id{}", req.getId());
            return new ResponseEntity("系统运行错误", HttpStatus.INTERNAL_SERVER_ERROR);
        }


    }

    @PostMapping("bind")
    public ResponseEntity bing(@RequestBody MemberRewardReq req) {
        return ResponseEntity.ok(rewardService.updateMemberByMemberId(req));
    }

    @GetMapping("getAll")
    public ResponseEntity getAllStore(@RequestParam("type") String type, Pageable pageable) {
        if (StringUtils.contains(type, "TIME")) {
            return ResponseEntity.ok(storeDao.findListByEnabledOrderByExpireTimeDesc(true, pageable));
        } else {
            return ResponseEntity.ok(storeDao.findListByEnabledOrderByExpireTimeDesc(true, pageable));
        }

    }

    @GetMapping("online-enabled")
    public ResponseEntity updateOnlineEnabled(@RequestParam("storeId") String storeId, @RequestParam("enabled") boolean onlineEnabled) {
        Store one = storeDao.findOne(storeId);
        one.setOnlineEnabled(onlineEnabled);
        storeDao.save(one);
        return ResponseEntity.ok().build();
    }


    @GetMapping("/replay/order")
    public ResponseEntity replayOrder(@RequestParam("orderId") String orderId) {
        Order order = orderDao.findOne(orderId.substring(4));
        if (order!=null){
            if (order.getStatus().equals(OrderStatus.CANCELED) || order.getStatus().equals(OrderStatus.INIT)){
                StockChangeTransaction stockChangeTransaction = stockTransactionDao.findByRefIdAndStockLevel(order.getId(),StockLevel.BAR);
                if (StringUtils.isNotBlank(order.getPayOrderId()) && stockChangeTransaction==null){
                    order.setStatus(OrderStatus.NOTSURE);
                    orderDao.save(order);
                    aliyunMNSSend.sendClint(order.getPayOrderId());
                }
                if (stockChangeTransaction!=null){
                    order.setStatus(OrderStatus.FINISHED);
                    orderDao.save(order);
                }
            }
        }
        return ResponseEntity.ok().build();
    }

    @GetMapping("/order/status")
    public ResponseEntity orderStatus(@RequestParam("orderId") String orderId) {
        Order order = orderDao.findOne(orderId.substring(4));
        return ResponseEntity.ok(order);
    }

    @GetMapping("/replay/order/status")
    public ResponseEntity replayOrder(@RequestParam("orderId") String orderId,@RequestParam("orderStatus") String orderStatus) {
        Order order = orderDao.findOne(orderId.substring(4));
        if (order!=null){
            order.setStatus(OrderStatus.valueOf(orderStatus));
            orderDao.save(order);
        }
        return ResponseEntity.ok().build();
    }


    @PostMapping("update-call")
    public ResponseEntity updateStore(@RequestBody UpdateStoreReq req) {
        return ResponseEntity.ok(storeService.updateStoreByStoreId(req));
    }
    @PostMapping("update-make")
    public ResponseEntity updateMake(@RequestBody UpdateStoreReq req) {
        Store store = storeDao.findOne(req.getStoreId());
        if (store!=null){
            store.setMakeEnabled(req.isMakeEnabled());
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            simpleDateFormat.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
            Date endTime = null;

            try {
                if (null!=req.getMakeEndTime()){
                    endTime = simpleDateFormat.parse(req.getMakeEndTime());
                }
            } catch (ParseException e) {
                log.info("时间转换异常");
                e.printStackTrace();
            }
            store.setMakeEndTime(endTime);
            log.info("店铺id{},时间{}",req.getStoreId(),endTime);
            storeDao.save(store);
        }
        return ResponseEntity.ok().build();
    }




    @PostMapping("update-storeReward")
    public ResponseEntity updateReward(@RequestBody UpdateRewardReq req) {

        return ResponseEntity.ok(storeService.updateReward(req));

    }

    @PostMapping("update-zero")
    public ResponseEntity updateZero(@RequestBody UpdateRewardReq req) {
        return ResponseEntity.ok(storeService.updateStoreByZero(req));
    }

    @PostMapping("update-discount")
    public ResponseEntity updateDiscount(@RequestBody UpdateRewardReq req) {
        return ResponseEntity.ok(storeService.updateStoreByDiscount(req));

    }


    @PostMapping("update-storeAccount")
    public ResponseEntity updateStoreAccount(@RequestBody UpdateStoreAccountReq req) {

        return ResponseEntity.ok(withdrawService.updateStoreWithdraw(req));

    }

    @GetMapping("get-storeAccount")
    public ResponseEntity getStoreAccount(Pageable pageable) {
        return ResponseEntity.ok(withdrawService.getAllWithDraw(pageable));

    }

    @GetMapping("get-store")
    public ResponseEntity getStore(@RequestParam("name") String name) {
        return ResponseEntity.ok(storeService.likeStoreName(name));
    }

    @GetMapping("find-allGift")
    public ResponseEntity findAllGift() {
        return ResponseEntity.ok(productService.findAllGift());
    }

    @GetMapping("/get-call-config")
    public ResponseEntity getCallConfig() {
        CallConfig one = callConfigDao.findOne(1);
        if (one==null){
            one= new CallConfig();
            one.setAppId("113030123");
            one.setKey("YKy7cS3wl2sfvmFfPJxSJDVO");
            one.setSecretKey("s2PxkWtdoBE0WkfPufiaHd9Xc5WiPhi2");
        }
        return ResponseEntity.ok(one);
    }

    @PostMapping("/update-call-config")
    public ResponseEntity UpdateCallConfig(@RequestBody UpdateConfigParams params) {
        CallConfig one = callConfigDao.findOne(1);
        if (one==null){
            one= new CallConfig();
            one.setAppId(params.getAppId());
            one.setKey(params.getKey());
            one.setSecretKey(params.getSecretKey());
            callConfigDao.save(one);
        }
        return ResponseEntity.ok(one);
    }

    @GetMapping("store-pay")
    public ResponseEntity getAllStorePay(Pageable pageable) {
        return ResponseEntity.ok(storePayDao.findAll(pageable));
    }

    @GetMapping("merge-order")
    public ResponseEntity mergeOrder(@RequestParam(value = "orderId", required = false) String orderId, @RequestParam(value = "code", required = false) String code, @RequestParam("channel") String channel) {
        return ResponseEntity.ok(orderService.changeOrderChannel(orderId, code, channel));
    }

    @GetMapping("merge-store-mobile")
    public ResponseEntity mergeStoreMobile(@RequestParam("source") String source, @RequestParam("target") String target, @RequestParam("storeId") String storeId) {
        return ResponseEntity.ok(employeeService.mergeStoreMobile(source, target, storeId));
    }

    @GetMapping("get-template")
    public ResponseEntity getTemplate(Pageable pageable) {
        return ResponseEntity.ok(productService.getTemplate(pageable));
    }

    @GetMapping("product-search")
    public ResponseEntity productSearch(@RequestParam("name") String name, Pageable pageable) {
        return ResponseEntity.ok(productService.productSearch(name, pageable));
    }

    @GetMapping("delete-product")
    public ResponseEntity deleteProduct(@RequestParam("id") String productId) {
        return ResponseEntity.ok(productService.deleteProduct(productId));
    }

    @PostMapping("update-product")
    public ResponseEntity updateProduct(@RequestBody SalesProductReq req) {
        return ResponseEntity.ok(productService.updateProduct(req));
    }

    @GetMapping("search-store-pay")
    public ResponseEntity searchStorePay(@RequestParam("name") String name) {
        String s = "%" + name + "%";
        return ResponseEntity.ok(storePayDao.findByStoreNameLike(s));
    }

    @PostMapping("/json/upload")
    public ResponseEntity imageUploadJson(@RequestBody String file) {
        try {
            String storeId = "9f5afd60-e952-11e7-a26a-83436326b6c5";
            Map<String, String> map = new HashMap<>();
            String id = RomdomGenerater.generateSeiNo(storeId);
            String imagePath = null;
            net.sf.json.JSONObject jsonObject = net.sf.json.JSONObject.fromObject(file);
            String image = jsonObject.getString("file");
            String imageReal = image.split(",")[1];
            if (!StringUtils.isBlank(image)) {

                String fileKey = "image/" + id + ".jpg";
                try {
                    byte[] decode = new Base64().decode(imageReal);
                    ByteArrayInputStream tInputStringStream = new ByteArrayInputStream(decode);
                    ImageFileOssUtil.imageUpload(tInputStringStream, fileKey);
                    imagePath = ImageFileOssUtil.getUrl(fileKey);
                    map.put("path", imagePath);
                } catch (FileNotFoundException e) {
                    return new ResponseEntity("文件未找到", HttpStatus.BAD_REQUEST);
                }
            } else {
                return new ResponseEntity("文件IO异常", HttpStatus.BAD_REQUEST);
            }
            return new ResponseEntity(map, HttpStatus.OK);
        } catch (Exception ex) {
            return new ResponseEntity("系统运行错误", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @PostMapping("update-gift")
    public ResponseEntity updateGift(@RequestBody GiftReq req) {
        return ResponseEntity.ok(productService.updateGift(req));
    }

    @PostMapping("set-call")
    public ResponseEntity setStoreCall(@RequestBody SetStoreCallTime callTime) {
        try {
            return ResponseEntity.ok(storeService.setStoreSecond(callTime));
        } catch (Exception e) {
            return new ResponseEntity("系统运行错误", HttpStatus.BAD_GATEWAY);
        }
    }


    @PostMapping("set-callPay")
    public ResponseEntity setStoreCall(@RequestBody CallPayService s) {
        try {
            return ResponseEntity.ok(callTranService.setCallStore(s.getStoreId()));
        } catch (Exception e) {
            return new ResponseEntity("系统运行错误", HttpStatus.BAD_GATEWAY);
        }
    }


    @PostMapping("/callService/scan-code")
    public ResponseEntity callServicePay(@RequestBody CallServicePayReq req) {
        PayTypeEnum payType = req.isType() ? PayTypeEnum.PAY_ALIPAY_NATIVE : PayTypeEnum.PAY_WX_NATIVE;
        SwiftPassQRCodePayResult result = paymentService.qrCallServiceCodePay(req.getId(), payType);
        Map<String, String> map = new HashMap();
        map.put("payMode", "THIRD_PARTY");
        map.put("url", result.getCodeImgURL());
        if (result.isSuccess()) {
            return ResponseEntity.ok(map);
        } else {
            return ResponseEntity.badRequest().body(result.getErrMsg());
        }
    }


    @PostMapping("tran/callBack")
    public ResponseEntity callServiceCallBack(@RequestBody String xml) {
        try {
            storeOrderService.handleCallOrder(xml);
        } catch (Exception ex) {
            log.error("storeCallBack pay fail:{}", xml);
        }
        return new ResponseEntity("isPaymentSuccess", HttpStatus.OK);
    }

    @GetMapping("rotation-tran")
    @Transactional
    public ResponseEntity findByTranId(@RequestParam("id") String id) {
        CallTran one = callTranDao.findOne(id);
        Store store = storeDao.findOne(one.getStoreId());
        Map<String, Object> map = new HashMap<>();
        if (one.getStatus().equals(OrderStatus.FINISHED)) {
            Calendar cal = Calendar.getInstance();
            cal.setTime(store.getCallEndTime());
            cal.add(Calendar.YEAR, 1);
            try {
                store.setCallEndTime(cal.getTime());
                store.setCall(true);
                storeDao.save(store);
                map.put("code", 200);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            map.put("code", 201);
        }
        return ResponseEntity.ok(map);
    }

    @GetMapping("get-bill")
    public ResponseEntity getOrderBill(@RequestParam("start") String start, @RequestParam("end") String end, @RequestParam("storeId") String storeId) throws Exception {
        if (redisService.canProceedCustom("getOrderBillProcess", 3)) {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            simpleDateFormat.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
            return ResponseEntity.ok(orderService.getStoreBill(simpleDateFormat.parse(start), simpleDateFormat.parse(end), storeId));
        }
        return ResponseEntity.status(400).body("请求过于频繁");
    }


}
